<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Redux 核心示例</title>
  </head>
  <body>
    <div>
      <p>count: <span id="value">0</span></p>
      <button id="btn1">+</button>
      <button id="btn2">-</button>
      <button id="btn3">当奇数时再加</button>
      <button id="btn4">隔一秒再加</button>
    </div>

    <script>
      // 自己动手实现一个 createStore 函数
      function createStore(reducer) {
        // 定义一个 state 数据
        let state;

        // getState
        function getState() {
          return state;
        }
        // dispatch
        function dispatch(action) {
          // 调用 reducer，返回值赋值给 state。实现state的更新
          state = reducer(state, action);
          // 还需要通知订阅者，传递给 subscribe 的回调函数执行一下
          listeners.forEach((listener) => {
            listener();
          });
        }
        // subscribe
        let listeners = []; // 存放着调用 subscribe 时，传递过来的回调
        function subscribe(listener) {
          listeners.push(listener);
        }

        // 默认执行一次 dispatch
        dispatch({ type: "@@redux/init.x.y.z" });

        return {
          getState,
          dispatch,
          subscribe,
        };
      }

      // 定义一个初始状态state
      const initialState = {
        count: 10,
      };

      // 定义一个reducer函数（用于修改state数据）
      function reducer(state = initialState, action) {
        console.log("reducer", state, action);

        switch (action.type) {
          case "increment":
            // state.count++; // 可以修改，但是不符合 redux 的规范。后续时间旅行不好使。
            // return state;
            return {
              count: state.count + 1,
            };

          case "decrement":
            return {
              count: state.count - 1,
            };

          default:
            return state;
        }
      }

      // 用 createStore 创建 store 对象
      const store = createStore(reducer);

      // 1. 创建 store 时，reducer 会执行一次。返回初始化的 state 数据
      //  传递的 state 为 undefined。
      //  传递的 action 是形如下面的对象 { type: '@@redux/INIT7.a.f.9.4.9' }

      // 2. store.getState() 用于获取仓库中的 state 数据。state 数据是 reducer 函数返回的
      // store.getState();

      // 3. 使用 store 中 state 的数据渲染页面
      const valueEl = document.querySelector("#value");
      function render() {
        const { count } = store.getState();
        valueEl.innerHTML = count;
      }

      render(); // 默认渲染一次
      // store.subscribe 订阅仓库state的变化
      store.subscribe(() => {
        console.log("state 发生变化了");
        // 重新 render 一下。
        render();
      });

      btn1.addEventListener("click", () => {
        // console.log(1);
        // 这个按钮点击之后，需要让 仓库中的 state 中的 count + 1. 需要调用 store.dispatch 传递 一个带有 type 属性的普通对象
        store.dispatch({ type: "increment" });
      });

      btn2.onclick = () => {
        store.dispatch({ type: "decrement" });
      };

      btn3.onclick = () => {
        // 判断当前传递数据是否为奇数
        const { count } = store.getState();
        if (count % 2 !== 0) {
          store.dispatch({ type: "increment" });
        }
      };

      btn4.onclick = () => {
        setTimeout(() => {
          store.dispatch({ type: "increment" });
        }, 1000);
      };
    </script>
  </body>
</html>
